package magnet.processor.instances.aspects.selector;

import magnet.processor.common.ValidationException;
import magnet.processor.instances.parser.AttributeParser;
import magnet.processor.instances.parser.ParserInstance;

import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import java.util.Arrays;
import java.util.List;

public class SelectorAttributeParser extends AttributeParser {

    private String DELIMITER = "[\\s|.]+";
    private List<String> OPERATORS = Arrays.asList(">", "<", ">=", "<=", "==", "!=", "in", "!in");

    private static volatile SelectorAttributeParser parser;

    private SelectorAttributeParser() {
        super("selector");
    }

    public static SelectorAttributeParser INSTANCE() {
        synchronized (SelectorAttributeParser.class) {
            if (parser == null) {
                synchronized (SelectorAttributeParser.class) {
                    parser = new SelectorAttributeParser();
                }
            }
        }
        return parser;
    }

    @Override
    public <E extends Element> ParserInstance<E> parse(Scope<E> scope, AnnotationValue value) throws ValidationException {
        ParserInstance instance = scope.getInstance().copy();
        instance.setSelector(parse(scope, value.getValue().toString()));
        return instance;
    }

    private <E extends Element> List<String> parse(Scope<E> scope, String selector) throws ValidationException {
        if (selector.isEmpty()) {
            return null;
        }
        String[] parsedSelector = selector.split(DELIMITER);
        boolean isSelectorInvalid = parsedSelector.length < 4 ||
                parsedSelector[0].isEmpty() ||
                parsedSelector[1].isEmpty() ||
                !OPERATORS.contains(parsedSelector[2]) ||
                parsedSelector[3].isEmpty();

        if (!isSelectorInvalid) {
            switch (parsedSelector[2]) {
                case "in":
                case "!in":
                    isSelectorInvalid = parsedSelector.length != 5;
                    break;
                default:
                    isSelectorInvalid = parsedSelector.length != 4;
                    break;
            }
        }

        if (isSelectorInvalid) {
            throw new ValidationException(scope.getElement(), "Invalid selector. Expected format:" +
                    " '[selector id].[selector field] [comparison operator] [value]'." +
                    " Supported comparison operators: $OPERATORS.");
        }

        return Arrays.asList(parsedSelector);
    }
}
